package org.bdware.irs.backend.controller;

import com.google.gson.Gson;
import com.nimbusds.jose.JOSEException;
import org.apache.log4j.Logger;
import org.bdware.bdoa.authentication.utils.JwtContext;
import org.bdware.irs.backend.dto.*;
import org.bdware.irs.backend.servicesImpl.*;
import org.bdware.irs.backend.utils.DOIParser;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.ECDSAVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.KeyType;
import org.bdware.bdoa.authentication.utils.JwxUtils;
import org.bdware.irp.stateinfo.StateInfoBase;
import org.bdware.irp.stateinfo.UserStateInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;


/**
 * 用户管理模块
 *
 * @RestController
 * @RequestMapping(value = "/doa/user")
 */
@RestController
@RequestMapping(value = "/doa/user")
public class LoginUserController {


    static Logger logger = Logger.getLogger(LoginUserController.class);


    @Autowired
    GrsUserServiceRocksImpl grsServiceImpl;

    @Autowired
    GrsService grsService;

    @Autowired
    IrsServiceStandAloneImpl irsService;
//    IrsServiceRemoteImpl irsService;


    //TODO 需要对用户身份做区分，分为普通用户和管理员用户，前端见到的功能需要区分
    //通过JWS来验证身份
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ResponseWrapper login(@RequestBody LoginUser loginUser) {
        logger.info("=======user login======");
        logger.info(loginUser.getDoi() + ", " + loginUser.getToken() + " , " + loginUser.getRole());
        String result = "登陆验证失败";
        ResponseWrapper<String> response = new ResponseWrapper<>(result);
        response.setSuccess(false);
        String publicKey = "";

        String type = DOIParser.getType(loginUser.getDoi());

        if (type.equals("irs_admin")) {
            //IRS管理员登陆
            Organization organization = grsService.getOrganization(loginUser.getDoi());
            if (organization == null)
                return response;
            publicKey = organization.getJwkKey();

        } else if (type.equals("dou")) {
            //repo或者reg的用户登陆
            StateInfoBase saveStateInfo = irsService.resolve(loginUser.getDoi());
            if (saveStateInfo == null) {
                return response;
            }
            UserStateInfo userStateInfo = UserStateInfo.fromStateInfoBase(saveStateInfo);
            publicKey = userStateInfo.getPubkey();
        } else if (type.equals("prefix")) {
            //GRS用户登陆
            User user = grsServiceImpl.getUser(loginUser.getDoi());
            if (user == null) {
                return response;
            }
            publicKey = user.getPublicKey();
        } else {
            return response;
        }


        boolean verified = false;
        try {
            JWK pkToVerify = JWK.parse(publicKey);
            // header.payload.signature "eyJhbGciOiJFUzI1NiIsImtpZCI6IjEyMzQ1NiJ9.aGVsbG8.UmGZzEhI8WPhu-FEu4IPRmCJpClTlPC-yYpVt5YW0GMLbKDlTVoG7QWyILWEsblHdAqkRHieRNnSVxySbl8pvA"
            JWSObject verify = JWSObject.parse(loginUser.getToken());
            JWSVerifier verifier = null;

            if (pkToVerify.getKeyType() == KeyType.RSA) {
                verifier = new RSASSAVerifier(pkToVerify.toRSAKey().toRSAPublicKey());
            } else if (pkToVerify.getKeyType() == KeyType.EC) {
                verifier = new ECDSAVerifier(pkToVerify.toECKey().toECPublicKey());
            } else {
                System.out.println("unsupported Algorithm");
            }
            verified = verify.verify(verifier);
            if (verified == true) {
                result = loginUser.getToken();
                response.setSuccess(true);
                response.setData(result);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        } finally {
            return response;
        }

    }


    /**
     *
     * @param doi
     * @param role 登陆角色，包括irs,registry,repository
     * @return
     * @throws JOSEException
     */
    @RequestMapping(value = "/currentUser", method = RequestMethod.GET)
    public ResponseWrapper getCurrentUser(String doi, String role) throws JOSEException {
        if (doi == null) {
            doi = (String) JwtContext.getDoi();
        }

        logger.info("====get current user with doi: " + doi + " , role: " + role);

        StateInfoBase stateInfoBase = new StateInfoBase();
        stateInfoBase.setIdentifier(doi);

        String type = DOIParser.getType(doi);

        if (type.equals("irs_admin")) {
            //IRS管理员登陆
            Organization organization = grsService.getOrganization(doi);
            if (organization == null)
                return new ResponseWrapper<>(new Gson().toJson(stateInfoBase));
            StateInfoBase saveStateInfo = organization.toStateInfoBase();
            saveStateInfo.getHandleValues().addProperty("access", "irs_admin");
            return new ResponseWrapper<>(new Gson().toJson(saveStateInfo));
        } else if (type.equals("dou")) {
            //IRS用户登陆
            StateInfoBase saveStateInfo = irsService.resolve(doi);
            if (saveStateInfo == null) {
                return new ResponseWrapper<>(new Gson().toJson(stateInfoBase));
            }
            UserStateInfo userStateInfo = UserStateInfo.fromStateInfoBase(saveStateInfo);
            //TODO 进一步区分是管理员还是普通用户
            if("registry".equals(role)) {
                userStateInfo.getHandleValues().addProperty("access", "reg_user");
                if(irsService.isManager(doi, role)){
                    userStateInfo.getHandleValues().addProperty("access", "reg_admin");
                }
            }else if("repository".equals(role)){
                userStateInfo.getHandleValues().addProperty("access", "repo_user");
                if(irsService.isManager(doi, role)){
                    userStateInfo.getHandleValues().addProperty("access", "repo_admin");
                }
            }else{
                userStateInfo.getHandleValues().addProperty("access", "normal_user");
            }
            return new ResponseWrapper<>(new Gson().toJson(userStateInfo));
        } else if (type.equals("prefix")) {
            //GRS用户登陆
            User user = grsServiceImpl.getUser(doi);
            if (user == null) {
                return new ResponseWrapper<>(new Gson().toJson(stateInfoBase));
            }
            UserStateInfo userStateInfo = user.toUserStateInfo();
            userStateInfo.getHandleValues().addProperty("access", "grs");
            return new ResponseWrapper<>(new Gson().toJson(userStateInfo));

        }
        return new ResponseWrapper<>(new Gson().toJson(stateInfoBase));
    }


    @RequestMapping(value = "/authWithJWT", method = RequestMethod.POST)
    public boolean authWithJWT() {
        return false;
    }


    @RequestMapping(value = "/crypto", method = RequestMethod.POST)
    public String crypto(@RequestBody Crypto cryptoData) {
        String result = null;
        if (cryptoData.getType() == 0) {
            //加密
            result = JwxUtils.encrypt(cryptoData.getSource(), cryptoData.getPrivateKey());
        } else {
            result = JwxUtils.decrypt(cryptoData.getEncryptedData(), cryptoData.getPublicKey());
        }
        return result;
    }

}
